using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualBasic;

namespace Lincolnwood.Foundation.Scheduling
{
    public sealed class YearlyRecurrencePattern : RecurrencePattern
    {

        private YearlyRecurrencePattern() : base()
        { }

        public YearlyRecurrencePattern(DateTime endDate, int yearInterval)
            : base(endDate, yearInterval)
        {            
        }

        public override DateTime FindClosestRecurrenceDate(RecurrableEventDefinition eventContext, DateTime expandBegin)
        {
            // Get the difference in years between the start of the expansion period and the start of the recurring event period.
            long dateDifferenceYrs =  DateAndTime.DateDiff(DateInterval.Year, 
                                                        eventContext.StartTime, 
                                                        expandBegin, 
                                                        FirstDayOfWeek.Sunday, 
                                                        FirstWeekOfYear.Jan1);

            // Compute how many recurrence intervals fall in the difference.
            // and round the result up to the closest whole number.
            Double exactIntervals = Convert.ToInt32(dateDifferenceYrs) / this.Interval;

            int minimumWholeIntervals = Convert.ToInt32(Math.Floor(exactIntervals));
            
            // Multiply the whole number by the interval
            // and add the product to the start of the recurring event.
            // This computes the closest event (or would be event)
            // to the start of our expansion period.
            DateTime closestRecurrence = eventContext.StartTime.AddYears(this.Interval * minimumWholeIntervals);

            if (expandBegin.Date.Subtract(closestRecurrence.Date).Ticks > 0)
                closestRecurrence = closestRecurrence.AddMonths(this.Interval);
            else if (expandBegin.Date.Subtract(closestRecurrence.Date).Ticks < 0)
                closestRecurrence = closestRecurrence.AddMonths(-this.Interval);

            if (closestRecurrence < eventContext.StartTime)
                closestRecurrence = eventContext.StartTime;

            return closestRecurrence;
        }

        public override DateTime GetNextRecurrenceDate(DateTime baseDate)
        {
            return baseDate.AddYears(this.Interval);
        }

        //public override IList<CalendarEvent> Expand(DateTime expandBegin, DateTime expandEnd)
        //{
        //    // The CalendarEvent that is to be expanded
        //    CalendarEvent evt = eventContext;

        //    // Collection of expanded events
        //    List<CalendarEvent> evtList = new List<CalendarEvent>();

        //    // create new CalendarEvents: 1 event per yearInterval(th) year           
        //    DateTime closestRecurrenceDate = this.FindClosestRecurrenceDate(expandBegin);

        //    // if the period of expansion overlaps the recurrence period
        //    if (this.StartDate <= expandEnd && expandBegin <= this.EndDate)
        //    {
        //        // begin generating CalendarEvents for each recurrence instance
        //        // within the overlaping period.
        //        for (DateTime currentDate = closestRecurrenceDate;
        //            currentDate <= this.EndDate && currentDate <= expandEnd;
        //            currentDate = currentDate.AddYears(this.Interval))
        //        {
        //            bool foundException = false;
        //            TimeSpan eventLength = evt.EndTime.Subtract(evt.StartTime);
        //            DateTime eventStartTime = currentDate;
        //            DateTime eventEndTime = currentDate.Add(eventLength);

        //            // check to see if this expanded event instance has an 
        //            // exception associated with it whose OriginalDate matches
        //            // the expanded event instance start date.
        //            for (int idx = 0; idx < this.Exceptions.Count; idx++)
        //            {
        //                // we can safely assume that there are no exceptions
        //                // if we reach the end of the list of sorted
        //                // exceptions without finding one or if we hit an event
        //                // with a start time greater than the expanded event instance's
        //                if (this.Exceptions[idx].OriginalDate > eventStartTime)
        //                    break;
        //                else
        //                {
        //                    // otherwise, if we find a match between the original date of the 
        //                    // exception and the currently expanded event instance
        //                    // and it is not deleted then add the exception
        //                    if (this.Exceptions[idx].OriginalDate.Date == eventStartTime.Date)
        //                    {
        //                        foundException = true;

        //                        if (!Exceptions[idx].Deleted &&
        //                                Exceptions[idx].StartTime <= expandEnd &&
        //                                Exceptions[idx].StartTime >= expandBegin)
        //                            evtList.Add(this.Exceptions[idx]);
        //                    }

        //                }
        //            }                    
        //            if (!foundException)
        //            {
        //                // if no exception is associated with this event then use the generic recurring event
        //                CalendarEvent recurringEvt = new CalendarEvent(evt.Id, evt.Name, evt.Description, eventStartTime, eventEndTime);
        //                recurringEvt.Recurrence = this;

        //                evtList.Add(recurringEvt);
        //            }
        //        }
        //    }
        //    return evtList;
        //}
    }
}
